package ooboo;

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.Timer;
import javax.swing.UIManager;

import ooboo.gui.MainDisplay;
import twitter4j.TwitterException;
import twitter4j.User;
import twitter4j.http.AccessToken;

public class Ooboo implements ActionListener
{
	private Object application;
    private Class<?> applicationListenerClass;

    Map listenerMap = Collections.synchronizedMap(new HashMap());
    private boolean enabledAboutMenu = true;
    private boolean enabledPreferencesMenu;
    private boolean aboutMenuItemPresent = true;
    private boolean preferencesMenuItemPresent;
    private ClassLoader classLoader;
    public static BufferedImage originalIcon = null;
	
	public static String curScreenName; // added a variable to store the current user.
	String users[];
	//private TrayIcon trayIcon;
	private MainDisplay display;
	
	public static int numNewTweets = 0;
	
	private Ooboo()
	{
		display = new MainDisplay();
		
		if(Assets.isFirstRun())
			firstRun();
		else
			normalInit();
		
		///*
		users = Storage.getAllScreenNames();
		display.getPostPanel().setScreenName(users[0]);
		display.setThreads(Storage.getThreads(users[0],50 + numNewTweets));
		Authenticator.getTweets(users[0]);
		curScreenName = users[0];
		//ImageCache.update(tweets);
		//Storage.store(users[0],tweets);
		display.setThreads(Storage.getThreads(users[0],75 + numNewTweets));
		
		//actionPerformed(null);//do the first update
		new Timer(60000,this).start(); // creates and starts the timer (make sure that its the swing timer not the util one.)
		
		/*/
		TweetThread[] threads = new TweetThread[3];
		
		threads[0] = new TweetThread(
				new StoredTweet(0,new Date(System.currentTimeMillis()),"Lorem ipsum dolor sit amet http://www.google.ca. consectetur adipiscing elit. In suscipit risus in dolor blandit scelerisque. Nullam at varius eros. Quisque sed.","ooboo","douglasmartin"),
				new StoredTweet[]{
					new StoredTweet(0,new Date(System.currentTimeMillis()),"Tired->tea->bag->travel->plane->wings->bird->seed->plant->veggies->salad->dressing->clothes->suit->Barney->dino->extinct->my energy #awesome #awesometweetistooawesomeformostclients","Twitter Opera Widget","NathanChalmers"),
					new StoredTweet(0,new Date(System.currentTimeMillis()),"@douglasmartin I'm sorry I don't speak latin (http://www.google.com)","TwitterFox","DosFX")});
		
		threads[1] = new TweetThread(
				new StoredTweet(0,new Date(System.currentTimeMillis()),"w w w w wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww","TwitterFox","DosFX"),
				new StoredTweet[]{
					new StoredTweet(0,new Date(System.currentTimeMillis()),"@DosFX Wow that was a lot of w's. Must've closed my laptop on my earbuds again.","TwitterFox","DosFX")});
		
		threads[2] = new TweetThread(
				new StoredTweet(0,new Date(System.currentTimeMillis()),"12345678911234567892123456789312345678941234567895123456789612345678971234567898123456789912345678901234567891123456789212345678931234567894 #numbers","ooboo","TheRealOoboo"),
				new StoredTweet[0]);
		
		display.setThreads(threads);
		//*/
		
		//System.out.println(Storage.getMaxID(users[0]));
		
		/*
		ImageIcon icon = new ImageIcon("images/icon.png");

		if(SystemTray.isSupported())
		{
			trayIcon = new TrayIcon(icon.getImage());
			trayIcon.setImageAutoSize(true);
			
			try
			{
				SystemTray.getSystemTray().add(trayIcon);
			}
			catch(AWTException e)
			{
				e.printStackTrace();
			}
		}
		//*/
		
		if (Assets.isMac()) {
			try {
	            final File file = new File("/System/Library/Java");
	            if(file.exists()) {
	                ClassLoader scl = ClassLoader.getSystemClassLoader();
	                Class<?> clc = scl.getClass();
	                if(URLClassLoader.class.isAssignableFrom(clc)) {
	                    Method addUrl  = URLClassLoader.class.getDeclaredMethod("addURL", new Class[] {URL.class});
	                    addUrl.setAccessible(true);
	                    addUrl.invoke(scl, new Object[] {file.toURI().toURL()});
	                }
	            }

	            Class<?> appClass = Class.forName("com.apple.eawt.Application");
	            application = appClass.getMethod("getApplication", new Class[0]).invoke(null, new Object[0]);
	            applicationListenerClass = Class.forName("com.apple.eawt.ApplicationListener");
	        } catch (ClassNotFoundException e) {
	            application = null;
	        } catch (IllegalAccessException e) {
	            throw new RuntimeException(e);
	        } catch (NoSuchMethodException e) {
	            throw new RuntimeException(e);
	        } catch (InvocationTargetException e) {
	            throw new RuntimeException(e);
	        } catch (MalformedURLException e) {
	            throw new RuntimeException(e);
	        }

		}
	}
	

	public void actionPerformed(ActionEvent e) //from the actionListener interface
	{
		new Thread() //this does the update in a separate thread so that the UI can continue to be redraw while the update is going on.
		{
		public void run()
		{
			Authenticator.getTweets(users[0]);
			if (numNewTweets != 0) {
				display.setThreads(Storage.getThreads(users[0],50 + numNewTweets));
			}
		}
		}.start();
	}


	
	private void normalInit()
	{
		Storage.connect(false);
		
		for(String screenName:Storage.getAllScreenNames())
			Authenticator.register(screenName,Storage.getAccessToken(screenName));
	}

	private void firstRun()
	{
		Storage.connect(true);
		
		AccessToken accessToken = Initializer.showWizard(display);
		try
		{
			User user = Authenticator.newUser(accessToken);
			Storage.addAccount(user.getScreenName(),accessToken);
			ImageCache.update(user.getScreenName(),user.getProfileImageURL());
		}
		catch(TwitterException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	private Object getNSApplication() throws ClassNotFoundException {
        try {
            Class<?> applicationClass = Class.forName("com.apple.cocoa.application.NSApplication");
            return applicationClass.getMethod("sharedApplication", new Class[0]).invoke(null, new Object[0]);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }

    public void setApplicationIconImage(BufferedImage image) {
        if (Assets.isMac()) {
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            try {
                ImageIO.write(image, "png", stream);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

            try {
                Class<?> nsDataClass = Class.forName("com.apple.cocoa.foundation.NSData");
                Constructor<?> constructor = nsDataClass.getConstructor(new Class[]{new byte[0].getClass()});

                Object nsData = constructor.newInstance(new Object[]{stream.toByteArray()});

                Class<?> nsImageClass = Class.forName("com.apple.cocoa.application.NSImage");
                Object nsImage = nsImageClass.getConstructor(new Class[]{nsDataClass}).newInstance(new Object[]{nsData});

                Object application = getNSApplication();

                application.getClass().getMethod("setApplicationIconImage", new Class[] {nsImageClass}).invoke(application, new Object[] {nsImage});

            } catch (ClassNotFoundException e) {

            } catch (NoSuchMethodException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            } catch (InvocationTargetException e) {
                throw new RuntimeException(e);
            } catch (InstantiationException e) {
                throw new RuntimeException(e);
            }

        }
    }

    public BufferedImage getApplicationIconImage() {
        if (Assets.isMac()) {

            try {
                Class<?> nsDataClass = Class.forName("com.apple.cocoa.foundation.NSData");
                Class<?> nsImageClass = Class.forName("com.apple.cocoa.application.NSImage");
                Object application = getNSApplication();
                Object nsImage = application.getClass().getMethod("applicationIconImage", new Class[0]).invoke(application, new Object[0]);

                Object nsData = nsImageClass.getMethod("TIFFRepresentation", new Class[0]).invoke(nsImage, new Object[0]);

                Integer length = (Integer) nsDataClass.getMethod("length", new Class[0]).invoke(nsData, new Object[0]);
                byte[] bytes = (byte[]) nsDataClass.getMethod("bytes", new Class[]{Integer.TYPE, Integer.TYPE}).invoke(nsData, new Object[]{Integer.valueOf(0), length});

                BufferedImage image = ImageIO.read(new ByteArrayInputStream(bytes));
                return image;

            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            } catch (InvocationTargetException e) {
                throw new RuntimeException(e);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

        }

        return null;
    }
    
    

    public void incrementIcon (int num) {
        BufferedImage newIcon = new BufferedImage(originalIcon.getWidth(), originalIcon.getHeight(), BufferedImage.TYPE_INT_ARGB);

        Graphics2D graphics = (Graphics2D) newIcon.getGraphics();

        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        graphics.setColor(Color.decode("#E40000"));

        graphics.drawImage(originalIcon, 0, 0, null);

        ImageIcon badgeIcon = new ImageIcon("images/badge.png");
        
        String numString = Integer.toString(num);
        
        graphics.setColor(Color.WHITE);
        graphics.setFont(new Font("Helvetica", Font.BOLD, 100));
        FontMetrics fontMetric = graphics.getFontMetrics();
        int numWidth = fontMetric.stringWidth(numString);
        int numHeight = fontMetric.getHeight();

        if (num < 10) {
        	numWidth = fontMetric.stringWidth("10");
        }
        
        graphics.drawImage(badgeIcon.getImage(), originalIcon.getWidth()-numWidth-92, 0, originalIcon.getWidth()-numWidth, 200, 0, 0, 23, badgeIcon.getIconHeight(), null);

        int targetX = (-92)+numWidth;
        int x = 0;
        int i = 0;
        
        while(x < targetX) {
        	graphics.drawImage(badgeIcon.getImage(), originalIcon.getWidth()-numWidth+(20*i), 0, originalIcon.getWidth()-numWidth+(20*(i+1)), 200, 23, 0, 28, badgeIcon.getIconHeight(), null);
        	i++;
        	x+=20;
        }
        	
        graphics.drawImage(badgeIcon.getImage(), originalIcon.getWidth()-92, 0, originalIcon.getWidth(), 200, 23, 0, badgeIcon.getIconWidth(), badgeIcon.getIconHeight(), null);
       
        if (num < 10) {
        	numWidth = 80;
        }
        
        graphics.drawString(numString, originalIcon.getWidth()-numWidth-46, numHeight+25);

        graphics.dispose();

        setApplicationIconImage(newIcon);
    }
	
	public static void main(String[] args)
	{	
		try
		{
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}

		Ooboo ooboo = new Ooboo();
		
		if (Assets.isMac()) {
			ImageIcon imgicon = new ImageIcon("images/DockIcon.png");
	    	originalIcon = Assets.toBufferedImage(imgicon.getImage());
	    	ooboo.setApplicationIconImage(originalIcon);
		}
		
	}
}
